<?php
/**
 * SocialEngine
 *
 * @category   Application_Core
 * @package    Core
 * @copyright  Copyright 2006-2010 Webligo Developments
 * @license    http://www.socialengine.net/license/
 * @version    $Id: Collection.php 7244 2010-09-01 01:49:53Z john $
 * @author     Sami
 */

/**
 * @category   Application_Core
 * @package    Core
 * @copyright  Copyright 2006-2010 Webligo Developments
 * @license    http://www.socialengine.net/license/
 */
class Core_Model_Item_Collection extends Core_Model_Item_Abstract implements Countable
{
  protected $_collectible_type;

  protected function getCollectionColumnName()
  {
    if (!empty($this->_collection_column_name)) {
  return $this->_collection_column_name;
      }
    return "collection_id";
  }

  public function getCollectibles($reverse = false)
  {
    $table = Engine_Api::_()->getItemTable($this->_collectible_type);
    $primary = current($table->info("primary"));
    $select = $table->select()
      ->where($this->getCollectionColumnName() . ' = ?', $this->getIdentity());

    if( $reverse )
    {
      $select->order($primary . ' DESC');
    }

    return $select->getTable()->fetchAll($select);
  }

  public function getCollectiblesSelect()
  {
    $table = Engine_Api::_()->getItemTable($this->_collectible_type);
    $orderCol = ( in_array('order', $table->info('cols')) ? 'order' : current($table->info('primary')) );
    $select = $table->select()
      ->where($this->getCollectionColumnName() . ' = ?', $this->getIdentity())
      ->order($orderCol.' ASC');
    return $select;
  }

  public function getCollectiblesPaginator()
  {
    return Zend_Paginator::factory($this->getCollectiblesSelect());
  }
  
  public function getCollectibleIndex($collectible, $reverse = false)
  {
    if( is_numeric($collectible) )
    {
      $collectible = Engine_Api::_()->getItem($this->_collectible_type, $collectible);
    }
    if( !($collectible instanceof Core_Model_Item_Collectible))
    {
      throw new Core_Model_Item_Exception('Improper argument passed to getNextCollectible');
    }

    if( isset($collectible->collection_index) )
    {
      return $collectible->collection_index;
    }

    //if( !isset($this->store()->collectible_index) || !isset($this->store()->collectible_index[$collectible->getIdentity()]) )
    //{
      $table = $collectible->getTable();
      $col = current($table->info("primary"));
      $select = $table->select()
        ->from($table->info('name'), $col)
        ->where($this->getCollectionColumnName() . ' = ?', $this->getIdentity())
        ;

      // Order supported
      if( isset($collectible->order) )
      {
        $select->order('order ASC');
      }
      // Identity
      else
      {
        $select->order($col.' ASC');
      }

      $i = 0;
      $index = 0;
      //$this->store()->collectible_index = array();
      foreach( $table->fetchAll($select) as $row )
      {
        if( $row->$col == $collectible->getIdentity() )
        {
          $index = $i;
        }
        $i++;
        //$this->store()->collectible_index[$row->$col] = $i++;
      }
    //}

    //$index = $this->store()->collectible_index[$collectible->getIdentity()];
    return ( $reverse ? $this->count() - $index : $index );
  }

  public function getCollectibleByIndex($index = 0, $reverse = false)
  {
    $table = Engine_Api::_()->getItemTable($this->_collectible_type);
    $hasOrder = ( in_array('order', $table->info('cols')));

    // Check index bounds
    $count = $this->count();
    if( $index >= $count )
    {
      $index -= $count;
    }
    else if( $index < 0 )
    {
      $index += $count;
    }

    $select = $table->select()
      ->where($this->getCollectionColumnName() . ' = ?', $this->getIdentity())
      ->limit(1, (int) $index)
      ;

    if( $hasOrder )
    {
      $select->order('order '.($reverse ? 'DESC' : 'ASC'));
    }
    else
    {
      $col = current($table->info("primary"));
      $select->order($col.' '.($reverse ? 'DESC' : 'ASC'));
    }
    
    $rowset = $table->fetchAll($select);
    if( null === $rowset )
    {
      // @todo throw?
      return null;
    }
    
    return $rowset->current();
  }
  
  public function getFirstCollectible()
  {
    return $this->getCollectibleByIndex(0);
  }

  public function getLastCollectible()
  {
    return $this->getCollectibleByIndex(0, true);
  }

  public function getPrevCollectible($collectible)
  {
    return $this->getCollectibleByIndex($this->getCollectibleIndex($collectible)-1);
  }

  public function getNextCollectible($collectible)
  {
    return $this->getCollectibleByIndex($this->getCollectibleIndex($collectible)+1);
  }

  public function count()
  {
    // @todo this doesn't work if collection_id is init to 0
    /*
    if( isset($this->collectible_count) )
    {
      return $this->collectible_count;
    }
     */

    if( isset($this->store()->collectible_count) )
    {
      return $this->store()->collectible_count;
    }

    $table = Engine_Api::_()->getItemTable($this->_collectible_type);
    $select = new Zend_Db_Select($table->getAdapter());
    $select->from($table->info('name'), new Zend_Db_Expr('COUNT(*) as count'))
      ->where($this->getCollectionColumnName() . " = ?", $this->getIdentity());
    $data = $table->getAdapter()->fetchRow($select);

    return $this->store()->collectible_count = (int) $data['count'];;
  }

  public function getCount()
  {
    trigger_error('Deprecated', E_USER_WARNING);
    return $this->count();
  }

  protected function _delete()
  {
    foreach( $this->getCollectibles() as $collectible )
    {
      $collectible->delete();
    }
    return parent::_delete();
  }

  
  // Order stuff

  public function getHighestOrder()
  {
    $table = Engine_Api::_()->getItemTable($this->_collectible_type);
    if( !in_array('order', $table->info('cols')) )
    {
      throw new Core_Model_Item_Exception('Unable to use order as order column doesn\'t exist');
    }
    
    $select = new Zend_Db_Select($table->getAdapter());
    $select
      ->from($table->info('name'), new Zend_Db_Expr('MAX(`order`) as max_order'))
      ->where($this->getCollectionColumnName() . ' = ?', $this->getIdentity())
      ;

    $data = $select->query()->fetch();
    $next = (int) @$data['max_order'];
    return $next;
  }
  
  public function setOrders($ids = null, $consecutive = true)
  {
    $table = Engine_Api::_()->getItemTable($this->_collectible_type);
    if( !in_array('order', $table->info('cols')) )
    {
      throw new Core_Model_Item_Exception('Unable to use order as order column doesn\'t exist');
    }

    $ids = (array) $ids;
    if( empty($ids) ) $consecutive = false;
    $col = current($table->info('primary'));
    $select = $table->select()
      ->where($this->getCollectionColumnName() . ' = ?', $this->getIdentity())
      ->order('order ASC')
      ;

    // Only re-ordering a chunk
    if( $consecutive && !empty($ids) )
    {
      $select->where($col.' IN(?)', $ids);
    }
    
    $collectibles = $table->fetchAll($select);

    // Non-consecutive unspecified
    if( empty($ids) )
    {
      $i = 0;
      foreach( $collectibles as $collectible )
      {
        $collectible->order = $i++;
        $collectible->save();
      }
    }

    // specified non-consecutive
    else if( $consecutive )
    {
      $i = count($ids);
      foreach( $table->fetchAll($select) as $collectible )
      {
        $order = array_search($collectible->getIdentity(), $ids);
        if( !$order )
        {
          $order = $i++;
        }
        $collectible->order = $order;
        $collectible->save();
      }
    }

    // specified consecutive
    else
    {
      // Build index
      $orderIndex = array();
      foreach( $collectibles as $collectible )
      {
        $orderIndex[] = $collectible->order;
      }
      sort($orderIndex);

      foreach( $collectibles as $collectible )
      {
        $index = array_search($collectible->getIdentity(), $ids);
        $collectible->order = $orderIndex[$index];
        $collectible->save();
      }
    }
    
    return $this;
  }
}